package com.dolphin.aiagentplatform.controller;

import com.dolphin.aiagentplatform.ai.client.ChatClientFactory;
import com.dolphin.aiagentplatform.ai.client.ChatClientStrategy;
import com.dolphin.aiagentplatform.ai.config.ChatStorageConfig;
import com.dolphin.aiagentplatform.ai.constant.AgentTypeConst;
import com.dolphin.aiagentplatform.ai.constant.ModelTypeConst;
import com.dolphin.aiagentplatform.ai.message.MessageVO;
import com.dolphin.aiagentplatform.ai.repository.ChatIdRepository;
import com.dolphin.aiagentplatform.common.BaseResponse;
import com.dolphin.aiagentplatform.exception.BusinessException;
import com.dolphin.aiagentplatform.model.dto.ChatSessionInfoDTO;
import com.dolphin.aiagentplatform.model.vo.user.UserVO;
import com.dolphin.aiagentplatform.service.ChatMessageService;
import com.dolphin.aiagentplatform.service.ChatSessionService;
import com.dolphin.aiagentplatform.service.ChatTransactionService;
import com.dolphin.aiagentplatform.service.UserLatestChatService;
import com.dolphin.aiagentplatform.utils.ChatIdGenerator;
import com.dolphin.aiagentplatform.utils.ResponseUtils;
import com.dolphin.aiagentplatform.utils.TokenManager;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

import java.util.List;

import static com.dolphin.aiagentplatform.constant.ResponseCodeConst.*;

/**
 * AI聊天控制器
 * 提供AI对话、会话管理等功能
 */
@RestController
@RequestMapping("/ai")
@RequiredArgsConstructor
@Slf4j
public class ChatController {

    // 为DeepSeek-r1提供的思考格式系统提示词
    private final String THINKING_MODEL_PROMPT =
            "\n在每个输出中，使用以下格式：{\n<think>\n{你的思考内容}\n</think>\n{你要输出的内容}\n}";
    @Resource
    private ChatIdRepository chatIdRepository;
    @Resource
    private ChatMemory chatMemory;
    @Resource
    private ChatIdGenerator chatIdGenerator;
    @Resource
    private ChatSessionService chatSessionService;
    @Resource
    private ChatMessageService chatMessageService;
    @Resource
    private UserLatestChatService userLatestChatService;
    @Resource
    private ChatStorageConfig chatStorageConfig;
    @Resource
    private ChatTransactionService chatTransactionService;
    @Resource
    private ChatClientFactory chatClientFactory;
    @Resource
    private TokenManager tokenManager;

    /**
     * 创建新对话
     *
     * @param agentType 聊天代理类型
     * @param request   HTTP请求
     * @return 新创建的聊天ID
     */
    @PostMapping("/chat/create-new-chat")
    public BaseResponse<String> createNewChat(
            @RequestParam(name = "agentType", required = false, defaultValue = "CHAT") String agentType,
            HttpServletRequest request) {
        try {
            // 检查用户是否已登录
            UserVO loginUser = tokenManager.getAndCheckLoginUser(request);

            // 验证代理类型
            AgentTypeConst agentTypeConst = AgentTypeConst.getByAgentType(agentType);
            if (agentTypeConst == null) {
                throw new BusinessException(NOT_FOUND_ERROR, "无效的会话类型");
            }

            // 生成新的聊天ID
            String chatId = chatIdGenerator.generateChatId(loginUser, agentTypeConst);

            // 保存聊天会话
            chatSessionService.saveChatSession(chatId, loginUser.getId(), agentTypeConst.toString());

            // 更新用户最近的聊天ID
            userLatestChatService.updateLatestChatId(loginUser.getId(), chatId, agentTypeConst.toString());

            log.debug("用户创建新对话，userId:{}, agentType:{}, chatId:{}", loginUser.getId(), agentType, chatId);
            return ResponseUtils.success(chatId);
        } catch (BusinessException e) {
            log.error("创建新对话失败: {}", e.getMessage());
            return ResponseUtils.error(e.getCode(), e.getMessage());
        } catch (Exception e) {
            log.error("创建新对话异常", e);
            return ResponseUtils.error(SYSTEM_ERROR, "系统异常");
        }
    }

    /**
     * 发送AI聊天请求并获取流式响应
     */
    @GetMapping(value = "/chat/{modelType}", produces = "text/html; charset=utf-8")
    public Flux<String> chat(
            @PathVariable("modelType") String modelType,
            @RequestParam(name = "systemPrompt", defaultValue = "") String systemPrompt,
            @RequestParam(name = "userPrompt") String userPrompt,
            @RequestParam(name = "temperature", defaultValue = "0.7") Double temperature,
            @RequestParam(name = "maxTokens", defaultValue = "2048") Integer maxTokens,
            @RequestParam(name = "chatId", required = false) String chatId,
            @RequestParam(name = "agentType", required = false, defaultValue = "CHAT") String agentType,
            HttpServletRequest request) {

        // 将异步操作包装在Flux.defer中
        return Flux.defer(() -> {
            try {
                log.debug("收到聊天请求: modelType={}, agentType={}, chatId={}", modelType, agentType, chatId);

                // 1. 检查用户是否已登录
                UserVO loginUser = tokenManager.getAndCheckLoginUser(request);
                Long userId = loginUser.getId();

                // 2. 检查模型类型是否合法
                ModelTypeConst modelTypeConst = ModelTypeConst.getByModelType(modelType);
                if (modelTypeConst == null) {
                    throw new BusinessException(NOT_FOUND_ERROR, "无效的模型类型");
                }

                // 3. 判断是否是需要特殊处理的思考模型(deepseek-r1)
                boolean isDeepseekModel = modelTypeConst == ModelTypeConst.DEEPSEEK_R1;

                // 4. 检查会话类型是否合法
                AgentTypeConst agentTypeConst = AgentTypeConst.getByAgentType(agentType);
                if (agentTypeConst == null) {
                    throw new BusinessException(PARAMS_ERROR, "无效的会话类型");
                }

                // 5. 处理聊天会话ID
                String finalChatId = chatTransactionService.processChatSession(chatId, userId, agentTypeConst);

                // 6. 处理系统提示词，特别是对思考模型
                String finalSystemPrompt = systemPrompt;
                if (isDeepseekModel) {
                    finalSystemPrompt = systemPrompt + THINKING_MODEL_PROMPT;
                }

                // 7. 获取对应模型的聊天客户端
                ChatClientStrategy chatClient = chatClientFactory.getChatClient(modelTypeConst);

                log.debug("发起AI对话请求，userId:{}, modelType:{}, chatId:{}", userId, modelType, finalChatId);

                // 8. 准备不可变变量，用于Lambda表达式
                String immutableChatId = finalChatId;
                final Long immutableUserId = userId;
                final String immutableSystemPrompt = finalSystemPrompt;

                // 9. 获取响应流并处理
                return chatClient.chat(finalSystemPrompt, userPrompt, temperature, maxTokens, finalChatId)
                        .collectList()
                        .flatMapMany(contentList -> {
                            // 10. 合并响应内容
                            String assistantResponse = String.join("", contentList);

                            try {
                                // 11. 在一个事务中保存完整的对话（系统提示、用户消息、助手响应）并更新会话标题
                                chatTransactionService.saveConversationAndUpdateTitle(
                                        immutableChatId,
                                        immutableUserId,
                                        immutableSystemPrompt,
                                        userPrompt,
                                        assistantResponse,
                                        modelType
                                );
                                log.debug("保存完整对话并更新会话标题成功: chatId={}", immutableChatId);
                            } catch (Exception e) {
                                log.error("保存对话到数据库失败", e);
                                // 即使保存失败，仍然返回响应内容给用户
                            }

                            // 12. 返回原始响应流
                            return Flux.fromIterable(contentList);
                        });

            } catch (BusinessException e) {
                log.error("AI对话请求失败，错误信息: {}", e.getMessage());
                return Flux.just("AI对话请求失败，错误信息: " + e.getMessage());
            } catch (Exception e) {
                log.error("AI对话请求异常", e);
                return Flux.just("AI对话请求异常，系统错误：" + e.getMessage());
            }
        });
    }

    /**
     * 检查两个系统提示词是否相同
     */
    private boolean isSameSystemPrompt(String existing, String newPrompt) {
        if (existing == null && newPrompt == null) {
            return true;
        }
        if (existing == null || newPrompt == null) {
            return false;
        }
        // 去除空格后比较
        return existing.trim().equals(newPrompt.trim());
    }

    /**
     * 获取支持的AI模型列表
     */
    @GetMapping("/models")
    public BaseResponse<List<String>> getSupportedModels(HttpServletRequest request) {
        try {
            // 验证用户登录状态
            tokenManager.getAndCheckLoginUser(request);

            // 获取所有支持的模型类型
            List<String> modelTypes = chatClientFactory.getAllSupportedModelTypes().stream()
                    .map(ModelTypeConst::getModelType)
                    .toList();
            return ResponseUtils.success(modelTypes);
        } catch (BusinessException e) {
            log.error("获取模型列表失败: {}", e.getMessage());
            return ResponseUtils.error(e.getCode(), e.getMessage());
        } catch (Exception e) {
            log.error("获取模型列表异常", e);
            return ResponseUtils.error(SYSTEM_ERROR, "系统异常");
        }
    }

    /**
     * 获取指定类型的聊天会话ID列表
     */
    @GetMapping("/chatId/{type}")
    public BaseResponse<List<String>> getChatIdListByAgentType(
            @PathVariable("type") String chatType,
            HttpServletRequest request) {
        try {
            // 验证用户登录状态
            UserVO loginUser = tokenManager.getAndCheckLoginUser(request);
            Long userId = loginUser.getId();

            // 验证聊天类型是否合法
            AgentTypeConst agentTypeConst = AgentTypeConst.getByAgentType(chatType);
            if (agentTypeConst == null) {
                throw new BusinessException(PARAMS_ERROR, "无效的会话类型");
            }

            // 获取指定类型的聊天会话ID列表
            List<String> chatIds = chatSessionService.getChatIdListByUserId(userId, chatType);

            log.debug("获取用户聊天ID列表成功，userId:{}, chatType:{}, count:{}", userId, chatType, chatIds.size());
            return ResponseUtils.success(chatIds);
        } catch (BusinessException e) {
            log.error("获取聊天ID列表失败: {}", e.getMessage());
            return ResponseUtils.error(e.getCode(), e.getMessage());
        } catch (Exception e) {
            log.error("获取聊天ID列表异常", e);
            return ResponseUtils.error(SYSTEM_ERROR, "系统异常");
        }
    }

    /**
     * 获取指定会话的聊天历史记录
     */
    @GetMapping("/history/{chatId}")
    public BaseResponse<List<MessageVO>> getChatHistoryByChatId(
            @PathVariable("chatId") String chatId,
            HttpServletRequest request) {
        try {
            // 验证用户登录状态
            UserVO loginUser = tokenManager.getAndCheckLoginUser(request);
            Long userId = loginUser.getId();

            // 验证chatId有效性和权限
            if (!StringUtils.hasText(chatId)) {
                throw new BusinessException(PARAMS_ERROR, "会话ID不能为空");
            }

            // 获取会话信息
            ChatSessionInfoDTO sessionInfo = chatSessionService.getChatSessionInfo(chatId);
            if (sessionInfo == null) {
                throw new BusinessException(NOT_FOUND_ERROR, "会话不存在");
            }

            // 获取聊天历史记录
            List<MessageVO> messageVOS = chatMessageService.getChatMessageVOsByChatId(chatId);

            log.debug("获取聊天历史记录成功，chatId:{}, messageCount:{}", chatId, messageVOS.size());
            return ResponseUtils.success(messageVOS);
        } catch (BusinessException e) {
            log.error("获取聊天历史记录失败: {}", e.getMessage());
            return ResponseUtils.error(e.getCode(), e.getMessage());
        } catch (Exception e) {
            log.error("获取聊天历史记录异常", e);
            return ResponseUtils.error(SYSTEM_ERROR, "系统异常");
        }
    }

    /**
     * 获取指定会话的详细信息
     */
    @GetMapping("/session/info/{chatId}")
    public BaseResponse<ChatSessionInfoDTO> getChatSessionInfo(
            @PathVariable("chatId") String chatId,
            HttpServletRequest request) {
        try {
            // 验证用户登录状态
            UserVO loginUser = tokenManager.getAndCheckLoginUser(request);
            Long userId = loginUser.getId();

            // 验证chatId有效性
            if (!StringUtils.hasText(chatId)) {
                throw new BusinessException(PARAMS_ERROR, "会话ID不能为空");
            }

            // 获取会话信息
            ChatSessionInfoDTO sessionInfo = chatSessionService.getChatSessionInfo(chatId);
            if (sessionInfo == null) {
                throw new BusinessException(NOT_FOUND_ERROR, "会话不存在");
            }

            log.debug("获取会话详细信息成功，chatId:{}", chatId);
            return ResponseUtils.success(sessionInfo);
        } catch (BusinessException e) {
            log.error("获取会话详细信息失败: {}", e.getMessage());
            return ResponseUtils.error(e.getCode(), e.getMessage());
        } catch (Exception e) {
            log.error("获取会话详细信息异常", e);
            return ResponseUtils.error(SYSTEM_ERROR, "系统异常");
        }
    }

    /**
     * 批量获取指定类型的会话详细信息
     */
    @GetMapping("/session/info/batch")
    public BaseResponse<List<ChatSessionInfoDTO>> getChatSessionInfoBatch(
            @RequestParam(name = "agentType", required = false, defaultValue = "CHAT") String agentType,
            HttpServletRequest request) {
        try {
            // 验证用户登录状态
            UserVO loginUser = tokenManager.getAndCheckLoginUser(request);
            Long userId = loginUser.getId();

            // 验证聊天类型是否合法
            AgentTypeConst agentTypeConst = AgentTypeConst.getByAgentType(agentType);
            if (agentTypeConst == null) {
                throw new BusinessException(PARAMS_ERROR, "无效的会话类型");
            }

            // 获取指定类型的会话列表
            List<ChatSessionInfoDTO> sessionInfoList = chatSessionService.getChatSessionInfoByUserId(userId, agentType);

            log.debug("批量获取会话信息成功，userId:{}, agentType:{}, count:{}", userId, agentType, sessionInfoList.size());
            return ResponseUtils.success(sessionInfoList);
        } catch (BusinessException e) {
            log.error("批量获取会话信息失败: {}", e.getMessage());
            return ResponseUtils.error(e.getCode(), e.getMessage());
        } catch (Exception e) {
            log.error("批量获取会话信息异常", e);
            return ResponseUtils.error(SYSTEM_ERROR, "系统异常");
        }
    }

    /**
     * 删除聊天会话
     *
     * @param chatId  聊天会话ID
     * @param request HTTP请求
     * @return 删除结果
     */
    @DeleteMapping("/session/{chatId}")
    public BaseResponse<Boolean> deleteChat(
            @PathVariable("chatId") String chatId,
            HttpServletRequest request) {
        try {
            // 验证用户登录状态
            UserVO loginUser = tokenManager.getAndCheckLoginUser(request);
            Long userId = loginUser.getId();

            // 验证chatId有效性
            if (!StringUtils.hasText(chatId)) {
                throw new BusinessException(PARAMS_ERROR, "会话ID不能为空");
            }

            // 删除聊天会话
            boolean result = chatSessionService.deleteChatSession(chatId, userId);
            
            if (!result) {
                throw new BusinessException(NOT_FOUND_ERROR, "删除失败，会话可能不存在或无权限删除");
            }

            log.info("删除聊天会话成功，userId:{}, chatId:{}", userId, chatId);
            return ResponseUtils.success(true);
        } catch (BusinessException e) {
            log.error("删除聊天会话失败: {}", e.getMessage());
            return ResponseUtils.error(e.getCode(), e.getMessage());
        } catch (Exception e) {
            log.error("删除聊天会话异常", e);
            return ResponseUtils.error(SYSTEM_ERROR, "系统异常");
        }
    }
}
